﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cemit.NetFramework;
using Cemit.PolyProto;
using System;
using System.Threading.Tasks;

namespace Cemit.NetFramework.Demo.PureFrameSync
{
    public class GameManager : MonoBehaviour
    {
        public string player1Name = "player1";
        public string player2Name = "player2";
        public string ip = "127.0.0.1";
        public int port = 4001;

        private int m_RoomId;

        // 模拟游戏调度者
        PolySocket gameDispatcher;
        // 直接操作PolySocket，模拟多客户端连接
        PolySocket player1;
        PolySocket player2;

        OperationFrameMaster player1FraneMaster;
        OperationFrameMaster player2FraneMaster;

        public void ConnectAndCreateGameRoom()
        {
            Debug.Log("开始游戏");
            player1 = new PolySocket()
                .SetLogger(Debug.Log, Debug.LogWarning, Debug.LogError);
            player2 = new PolySocket()
                .SetLogger(Debug.Log, Debug.LogWarning, Debug.LogError);

            gameDispatcher = new PolySocket()
                .SetLogger(Debug.Log, Debug.LogWarning, Debug.LogError);

            // 调度中心
            gameDispatcher.Connect(ip, port, OnConnectionSucceeded)
                .RegisterToFireMessage()
                .RegisterToPingUpdate();
        }

        private void OnConnectionSucceeded()
        {
            Msg_Game_CreateRoom createRoomMsg = new Msg_Game_CreateRoom();
            createRoomMsg.Player.Add(player1Name);
            createRoomMsg.Player.Add(player2Name);

            //模拟创建房间
            gameDispatcher.Send(createRoomMsg)
                .AddCallback<Msg_Game_RoomId>(OnHasGottedRoomId);
        }

        public void JoinPlayer1()
        {
            player1FraneMaster = new OperationFrameMaster();

            player1.Connect(ip, port, () => OnPlayerConnect(player1, player1Name, player1FraneMaster))
               .RegisterToFireMessage()
               .RegisterToPingUpdate();

            player1.AddMessageListener<F>(
                m => player1FraneMaster.AddFrame((F)m));
        }

        public void JoinPlayer2()
        {
            player2FraneMaster = new OperationFrameMaster();

            player2.Connect(ip, port, () => OnPlayerConnect(player2, player2Name, player2FraneMaster))
                .RegisterToFireMessage()
                .RegisterToPingUpdate();

            player2.AddMessageListener<F>(
                m => player2FraneMaster.AddFrame((F)m));
        }

        private void OnHasGottedRoomId(Msg_Game_RoomId msg)
        {   
            Debug.Log("房间已创建, ID：" + msg.Index);
            m_RoomId = msg.Index;
        }

        private void OnPlayerConnect(PolySocket player, string name, OperationFrameMaster frameMaster)
        {
            Debug.Log(name + " 已连接");
            player.Send(new Msg_Net_Login { Id = name })
                .AddCallback<Msg_Net_LoginResult>((m) => OnPlayerLogined(m, name, frameMaster));
        }

        public void Player1Operation()
        {
            player1.Send(new O
            {
                RoomId = m_RoomId,
                Operation = UnityEngine.Random.Range(0, 10).ToString() 
                + "+"
            });
        }
        public void Player2Operation()
        {
            player1.Send(new O
            {
                RoomId = m_RoomId,
                Operation = UnityEngine.Random.Range(0, 10).ToString()
                + "+"
            });
        }

        private void OnPlayerLogined(Msg_Net_LoginResult msg, string name, OperationFrameMaster frameMaster)
        {
            if (msg.Result != LoginResult.Successful)
            {
                Debug.Log(name + " 登录失败！" + msg.Result);
                return;
            }

            Debug.Log(name + " 已登录");

            Task.Run(async () => 
            {
                while (true)
                {
                    await Task.Delay(66);
                    
                    //实际游戏中对于叠加的帧率可以做加速处理（所有游戏时间以这里叠加的66ms个数为准）
                    while (frameMaster.Remain != 0)
                    {
                        int index = frameMaster.ReadFrame(out IEnumerable<string> o);

                        foreach (var item in o)
                        {
                            if (!string.IsNullOrEmpty(item))
                            {
                                Debug.Log($"{name}: {index}-{item}");
                            }
                        }
                    }
                }
            });
        }
    }
}